﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kokomo.Mirror.PeFormat;
using System.IO;

namespace Kokomo.Mirror.Ia32
{
	public class NativeProcedureInfo
	{
		internal NativeProcedureInfo(
			PeModule module,
			uint rva,
			string decoratedName
			)
		{
			if (module == null) throw new ArgumentNullException("module");

			if (!module.IsValidRva(rva))
				throw new ArgumentException("Invalid base address");

			this.Module = module;
			this.Rva = rva;
			this.DecoratedName = decoratedName;
		}

		public PeModule Module { get; private set; }
		public string DecoratedName { get; private set; }
		public uint Rva { get; private set; }

		public string PrincipalName
		{
			get
			{
				if (this.DecoratedName == null) return null;
				string principalName = DebugHelper.UndecorateSymbolName(this.DecoratedName, UndecorateOptions.NameOnly);
				return principalName;
			}
		}

		public long BaseAddress
		{
			get { return this.Module.RvaToAbsolute(this.Rva); }
		}

		public Stream GetBody()
		{
			SectionHeader section = this.Module.FindSectionContainingRva(this.Rva);

			if (section == null) throw new ArgumentException("The RVA does not exist in a section within the module");

			byte[] sectionData = this.Module.ReadSectionData(section.Name);
			Stream sectionStream = new MemoryStream(sectionData);

			sectionStream.Position = (this.Rva - section.VirtualAddress);

			return sectionStream;
		}
		public Ia32Disassembly Disassemble()
		{
			Stream stream = this.GetBody();

			IaDisassembler disassembler = this.Module.GetDisassembler();
			Ia32Disassembly disassembly = disassembler.Disassemble(
				stream,
				this.BaseAddress
				);
			return disassembly;
		}
	}
}
